// 公网中使用
const pc = new RTCPeerConnection({
    iceServers: [
        // 目前我在用的，免费STUN 服务器
        {
            urls: 'stun:stun.voipbuster.com ',
        },
        // 谷歌的好像都失效了，不过你们可以试试
        {
            urls: 'stun:stun.l.google.com:19301',
            // urls: 'stun:stun.l.google.com:19302',
            // urls: 'stun:stun.l.google.com:19303',
            // ...
        },
        // TURN 服务器,这个对服务器压力太大了，目前没找到免费的，后续我在自己的服务器上弄一个
        {
            urls: 'turn:turn.xxxx.org',
            username: 'webrtc',
            credential: 'turnserver',
        },
        {
            urls: 'turn:turn.ap-southeast-1.aliyuncs.com:443?transport=tcp',
            username: 'test',
            credential: 'test',
        },
    ],
})


// 初始化
async function init(params: type) {
    // 获取本地端视频标签
    const localVideo = document.getElementById('local') as HTMLVideoElement
    // 获取远程端视频标签
    const remoteVideo = document.getElementById('remote') as HTMLVideoElement

    // 采集本地媒体流
    const localStream = await navigator.mediaDevices.getUserMedia({
        video: true,
        audio: true,
    })
    // 设置本地视频流
    localVideo.srcObject = localStream

    // 不推荐使用：已经过时的方法 [addStream API](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addStream)
    // pc.addStream(localStream);

    // 添加本地媒体流的轨道都添加到 RTCPeerConnection 中
    localStream.getTracks().forEach((track) => {
        pc.addTrack(track, localStream)
    })

    // 监听远程流，方法一：
    pc.ontrack = (event) => {
        remoteVideo.srcObject = event.streams[0]
    }

    // 方法二：你也可以使用 addStream API，来更加详细的控制流的添加
    // const remoteStream: MediaStream = new MediaStream()
    // pc.ontrack = (event) => {
    //   event.streams[0].getTracks().forEach((track) => {
    //     remoteStream.addTrack(track)
    //   })
    //   // 设置远程视频流
    //   remoteVideo.srcObject = remoteStream
    // }
}

// 创建本地/远程 SDP 描述, 用于描述本地/远程的媒体流
let offerSdp = ''
let answerSdp = ''

const createOffer = async () => {
    // 创建 offer
    const offer = await pc.createOffer()
    // 设置本地描述
    await pc.setLocalDescription(offer)
    // await pc.setLocalDescription()
    // 到这里，我们本地的 offer 就创建好了，一般在这里通过信令服务器发送 offerSdp 给远端

    // 监听 RTCPeerConnection 的 onicecandidate 事件，当 ICE 服务器返回一个新的候选地址时，就会触发该事件
    pc.onicecandidate = async (event) => {
        if (event.candidate) {
            offerSdp.value = JSON.stringify(pc.localDescription)
        }
    }
}

const offer = await peerConnection.createOffer()
await peerConnection.setLocalDescription(offer)
console.log(peerConnection)

// 不传参数，默认调用 peerConnection.createOffer()
await peerConnection.setLocalDescription()
console.log(peerConnection)


const createAnswer = async () => {
    // 解析字符串
    const offer = JSON.parse(offerSdp)
    pc.onicecandidate = async (event) => {
        // Event that fires off when a new answer ICE candidate is created
        if (event.candidate) {
            answerSdp = JSON.stringify(pc.localDescription)
        }
    }
    await pc.setRemoteDescription(offer)
    const answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)
}

// 添加 answer(应答)
const addAnswer = async () => {
    const answer = JSON.parse(answerSdp)
    if (!pc.currentRemoteDescription) {
        pc.setRemoteDescription(answer)
    }
}

// 虚拟背景的 canvas中的图片数据
let backgroundImageData: ImageData
// 获取背景图像数据
function getBackgroundImageData() {
    const backgroundCanvas = document.querySelector(
        '#backgroundImg',
    ) as HTMLCanvasElement
    const backgroundCtx = backgroundCanvas.getContext('2d')!
    const img = new Image()
    img.src = 'https://xxxx.png'
    img.onload = () => {
        backgroundCtx.drawImage(
            img,
            0,
            0,
            backgroundCanvas.width,
            backgroundCanvas.height,
        )

        backgroundImageData = backgroundCtx.getImageData(
            0,
            0,
            backgroundCanvas.width,
            backgroundCanvas.height,
        )
    }
}

// 成功加入房间
socket.on('joined', (room, id) => {
    ElMessage.success('🦄🦄🦄成功加入房间')
    createOffer()
})

// 创建 offer
async function createOffer() {
    // 当一个新的offer ICE候选人被创建时触发事件
    peerConnection.onicecandidate = async (event) => {
        if (event.candidate) {
            offerSdp = JSON.stringify(peerConnection.localDescription)
            // 发送 offer
            if (offerSdp) {
                socket.emit('offer', {
                    userId,
                    roomId: roomId.value,
                    sdp: offerSdp,
                })
            }
        }
    }
    const offer = await peerConnection.createOffer()
    await peerConnection.setLocalDescription(offer)
}

// 创建 answer
async function createAnswer(val: string) {
    const offer = JSON.parse(val)
    peerConnection.onicecandidate = async (event) => {
        // 当一个新的 answer ICE candidate 被创建时
        if (event.candidate) {
            socket.emit('answer', {
                userId,
                roomId: roomId.value,
                sdp: JSON.stringify(peerConnection.localDescription),
            })
        }
    }
    await peerConnection.setRemoteDescription(offer)
    const answer = await peerConnection.createAnswer()
    await peerConnection.setLocalDescription(answer)
}

const createAnswer = async () => {
    // 解析字符串
    const offer = JSON.parse(offerSdp)
    pc.onicecandidate = async (event) => {
        // Event that fires off when a new answer ICE candidate is created
        if (event.candidate) {
            answerSdp = JSON.stringify(pc.localDescription)
        }
    }
    await pc.setRemoteDescription(offer)
    const answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)
}

// 添加 answer(应答)
const addAnswer = async () => {
    const answer = JSON.parse(answerSdp)
    if (!pc.currentRemoteDescription) {
        pc.setRemoteDescription(answer)
    }
}

// 离开房间
function handleLeave() {
    // 关闭对等连接
    peerConnection.close()
    // 发送离开的消息
    socket.emit('leave', { userId, roomId: roomId.value })
    // 关闭socket连接
    socket.disconnect()
}

